home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-07-28 | 24.5 KB | 1,167 lines | [TEXT/KAHL] |
- /*
- File: HeapTools.cp
-
- Copyright: © 1991-1994 by Apple Computer, Inc.
- All rights reserved.
-
- Part of the AOCE Sample SMSAM Package. Consult the license
- which came with this software for your specific legal rights.
-
- */
-
-
-
- #pragma trace off
-
- #ifndef __HEAPTOOLS__
- #include "HeapTools.h"
- #endif
-
- #ifndef __CURSORCTL__
- // #include "CursorCtl.h"
- #endif
-
- #ifndef __RESOURCES__
- #include "Resources.h"
- #endif
-
- #ifndef __STANDARDFILE__
- #include "StandardFile.h"
- #endif
-
- #ifndef __ERRORS__
- #include "Errors.h"
- #endif
-
- #ifndef __STDARG__
- #include "StdArg.h"
- #endif
-
- #ifndef __NEWDELETE__
- #include "NewDelete.h"
- #endif
-
- #ifndef __STRING__
- #include "String.h"
- #endif
-
- #ifndef __STDIO__
- #include "StdIO.h"
- #endif
-
- #ifndef __DEBUGGINGGEAR__
- #include "DebuggingGear.h"
- #endif
-
- #ifndef __DIRECTOBJECT__
- #include "DirectObject.h"
- #endif
-
- #ifndef __HANDLEOBJECT__
- #include "HandleObject.h"
- #endif
-
- extern ostream& DumpHex (ostream& s, const void *pv, unsigned long size);
- extern short gBovineWorkingVRefNum;
- extern long gBovineTempDirID;
-
- #pragma segment HeapTools
-
- const OSType kHeapArchiveCreator = 'MPS ';
- const OSType kHeapArchiveType = 'HEAP';
-
- /***********************************|****************************************/
- /***********************************|****************************************/
-
- struct LookupEntry
- {
- const void* fIdentifier;
- Ptr fInfo;
- };
-
- static LookupEntry** gLookupVector = nil;
- static unsigned long gLookupCount = 0;
-
- /***********************************|****************************************/
-
- void Register ( const void* identifier, const char* file, unsigned long line )
- {
- if ( gLookupVector )
- {
- ::HUnlock ( (Handle) gLookupVector );
- ::SetHandleSize ( (Handle) gLookupVector, ( gLookupCount + 1 ) * sizeof ( LookupEntry ) );
- }
- else
- {
- gLookupVector = (LookupEntry**) ::NewHandleSys ( sizeof ( LookupEntry ) );
- }
-
- if ( !MemError () )
- {
- ::MoveHHi ( (Handle) gLookupVector );
- ::HLock ( (Handle) gLookupVector );
- ( *gLookupVector ) [ gLookupCount ].fIdentifier = identifier;
-
- if ( file )
- {
- char buffer [ 64 ];
- unsigned long length = ::sprintf ( buffer, "%s:%li", file, line ) + 1;
- Ptr info = ::NewPtrSys ( length );
-
- if ( info )
- ::BlockMove ( buffer, info, length );
-
- ( *gLookupVector ) [ gLookupCount ].fInfo = info;
- }
- else
- {
- ( *gLookupVector ) [ gLookupCount ].fInfo = nil;
- }
-
- gLookupCount++;
- }
- }
-
- /***********************************|****************************************/
-
- void Unregister ( const void* identifier )
- {
- register unsigned long index = gLookupCount;
-
- while ( index-- > 0 )
- {
- if ( ( *gLookupVector ) [ index ].fIdentifier == identifier )
- {
- if ( ( *gLookupVector ) [ index ].fInfo )
- ::DisposePtr ( ( *gLookupVector ) [ index ].fInfo );
-
- if ( index < --gLookupCount )
- ::BlockMove ( ( *gLookupVector ) + index + 1, ( *gLookupVector ) + index, ( gLookupCount - index ) * sizeof ( LookupEntry ) );
-
- ::HUnlock ( (Handle) gLookupVector );
- ::SetHandleSize ( (Handle) gLookupVector, gLookupCount * sizeof ( LookupEntry ) );
- ::MoveHHi ( (Handle) gLookupVector );
- ::HLock ( (Handle) gLookupVector );
-
- break;
- }
- }
- }
-
- /***********************************|****************************************/
-
- LookupEntry* Find ( const void* identifier )
- {
- register unsigned long index = gLookupCount;
-
- while ( index-- > 0 )
- if ( ( *gLookupVector ) [ index ].fIdentifier == identifier )
- return ( *gLookupVector ) + index;
-
- return nil;
- }
-
- /***********************************|****************************************/
- /***********************************|****************************************/
-
- inline OSErr Write ( short r, const void* p, unsigned long l )
- {
- long b = l;
- return ::FSWrite ( r, &b, p );
- }
-
- /***********************************|****************************************/
-
- inline OSErr Read ( short r, void* p, unsigned long l )
- {
- long b = l;
- return ::FSRead ( r, &b, p );
- }
-
- /***********************************|****************************************/
- /***********************************|****************************************/
-
- BlockInfo::BlockInfo ():
- fZone ( nil ),
- fStart ( nil ),
- fMode32 ( GetMMUMode () ),
- fMarked ( false )
- {
- }
-
- /***********************************|****************************************/
-
- BlockInfo::BlockInfo ( const Zone* zone ):
- fZone ( zone ),
- fStart ( nil ),
- fMode32 ( GetMMUMode () ),
- fMarked ( false )
- {
- }
-
- /***********************************|****************************************/
-
- BlockInfo::BlockInfo ( const BlockInfo& that ):
- fZone ( that.fZone ),
- fStart ( that.fStart ),
- fHeader ( that.fHeader ),
- fMode32 ( that.fMode32 ),
- fMarked ( that.fMarked )
- {
- }
-
- /***********************************|****************************************/
-
- BlockInfo::~BlockInfo ()
- {
- }
-
- /***********************************|****************************************/
-
- BlockInfo&
- BlockInfo::operator = ( const BlockInfo& that )
- {
- if ( this != &that )
- {
- fZone = that.fZone;
- fStart = that.fStart;
- fHeader = that.fHeader;
- fMode32 = that.fMode32;
- fMarked = false;
- }
-
- return *this;
- }
-
- /***********************************|****************************************/
-
- Boolean
- BlockInfo::operator == ( register const BlockInfo& that ) const
- {
- if ( fMode32 != that.fMode32 )
- return false;
- else if ( fHeader.f32.fType != that.fHeader.f32.fType )
- return false;
- else if ( GetIdentifierAddress () != that.GetIdentifierAddress () )
- return false;
- else if ( GetLogicalSize () != that.GetLogicalSize () )
- return false;
-
- return true;
- }
-
- /***********************************|****************************************/
-
- const void*
- BlockInfo::GetIdentifierAddress () const
- {
- if ( !fZone )
- {
- return fStart;
- }
- else if ( fHeader.f32.fType == kRelocatable )
- {
- if ( fMode32 )
- return (Handle) ( (unsigned long) fHeader.f32.u.fRelativeHandle + (unsigned long) fZone );
- else
- return (Handle) ( (unsigned long) fHeader.f24.u.fRelativeHandle + (unsigned long) fZone );
- }
- else
- {
- return (const void*) ( (unsigned long) fStart + BlockHeaderSize () );
- }
- }
-
- /***********************************|****************************************/
-
- const void* BlockInfo::GetLogicalStart () const
- {
- if ( !fZone )
- {
- return nil;
- }
- else if ( fHeader.f32.fType == kRelocatable )
- {
- if ( fMode32 )
- return *(Handle) ( (unsigned long) fHeader.f32.u.fRelativeHandle + (unsigned long) fZone );
- else
- return *(Handle) ( (unsigned long) fHeader.f24.u.fRelativeHandle + (unsigned long) fZone );
- }
- else
- {
- return (const void*) ( (unsigned long) fStart + BlockHeaderSize () );
- }
- }
-
- /***********************************|****************************************/
-
- OSErr BlockInfo::Write ( short refNum ) const
- {
- ::Write ( refNum, &((BlockInfo*)this)->fMode32, sizeof ( fMode32 ) );
- const void* address = GetIdentifierAddress ();
- ::Write ( refNum, &address, sizeof ( address ) );
-
- if ( fMode32 )
- return ::Write ( refNum, &((BlockInfo*)this)->fHeader.f32, sizeof ( fHeader.f32 ) );
- else
- return ::Write ( refNum, &((BlockInfo*)this)->fHeader.f24, sizeof ( fHeader.f24 ) );
- }
-
- /***********************************|****************************************/
-
- OSErr BlockInfo::Read ( short refNum )
- {
- fZone = nil;
- ::Read ( refNum, &fMode32, sizeof ( fMode32 ) );
- ::Read ( refNum, &fStart, sizeof ( fStart ) );
-
- if ( fMode32 )
- return ::Read ( refNum, &fHeader.f32, sizeof ( fHeader.f32 ) );
- else
- return ::Read ( refNum, &fHeader.f24, sizeof ( fHeader.f24 ) );
- }
-
- /***********************************|****************************************/
-
- void
- BlockInfo::Set ( const void* blockHeader )
- {
- fStart = blockHeader;
-
- if ( fMode32 )
- fHeader.f32 = *(const BlockHeader32*) blockHeader;
- else
- fHeader.f24 = *(const BlockHeader24*) blockHeader;
- }
-
- /***********************************|****************************************/
-
- ostream&
- BlockInfo::operator >> ( ostream& s ) const
- {
- if ( fMode32 )
- return Stream32 ( s );
- else
- return Stream24 ( s );
- }
-
- /***********************************|****************************************/
-
- ostream&
- StreamType ( ostream& s, BlockInfo::BlockType type )
- {
- switch ( type )
- {
- case BlockInfo::kNonrelocatable:
- s << "ptr";
- break;
-
- case BlockInfo::kRelocatable:
- s << "handle";
- break;
-
- case BlockInfo::kFree:
- s << "free";
- break;
- }
-
- return s;
- }
-
- /***********************************|****************************************/
-
- ostream&
- BlockInfo::Stream24 ( ostream& s ) const
- {
- s << (void*) GetIdentifierAddress () << ", ";
- StreamType ( s, (BlockType) fHeader.f24.fType );
- return s << ", " << GetLogicalSize ();
- }
-
- /***********************************|****************************************/
-
- inline unsigned long min ( unsigned long a, unsigned long b )
- {
- return ( a < b ) ? a : b ;
- }
-
- /***********************************|****************************************/
-
- static void ShowBlockData ( ostream& s, const void* start, unsigned long size )
- {
- size = min ( size, 8 );
-
- s << "|";
- for ( unsigned short i = 0; i < size; ++ i )
- { unsigned char c = ((unsigned char *) start)[i];
- c = ( c < 32 ) ? ' ' : c;
- s << c;
- };
-
- s << " | $";
- for ( i = 0; i < size; ++ i )
- s << hex << (unsigned short) ((unsigned char*) start)[i] << dec << " ";
- }
-
- /***********************************|****************************************/
- ostream&
- BlockInfo::Stream32 ( ostream& s ) const
- {
- const void* start = GetLogicalStart ();
- const void* identifier = GetIdentifierAddress ();
- unsigned long size = GetLogicalSize ();
-
- extern void * g2020HalfGateway;
- if ( g2020HalfGateway == identifier )
- Debugger();
-
- s << (void*) identifier << ", ";
- StreamType ( s, (BlockType) fHeader.f32.fType );
- s << ", "; s.width ( 5 ); s << size;
-
- if ( fHeader.f32.fType == kRelocatable )
- {
- if ( fHeader.f32.fLocked )
- s << ", locked";
-
- if ( fHeader.f32.fPurgeable )
- s << ", purgeable";
-
- if ( fHeader.f32.fResource && fZone )
- {
- Str255 name;
- short id = 0;
- char type [ 5 ];
- type [ 4 ] = 0;
-
- ::GetResInfo ( (Handle) identifier, &id, (OSType*) &type, name );
-
- if ( !ResError () )
- {
- s << ", " << (char*) &type << " " << id;
-
- if ( name [ 0 ] > 0 )
- {
- name [ name [ 0 ] + 1 ] = 0;
- s << " \"" << (char*) name + 1 << "\"";
- }
- }
- }
- }
- s << flush;
-
- #if defined ( debug )
-
- if ( fZone && start )
- {
- #if THINK_CPLUS
- // Think C++ doesn't use HandleObjects, so they're really just DirectObjects.
- // Additionally, it always stuffs '$FFFF' into the first word of
- // every allocated block ( for some reason ) and so the real object
- // data starts 'after' the first word.
- const void * actualDataStart = ( (char*) identifier ) + 2;
- if ( ( fHeader.f32.fType != kRelocatable ) &&
- ( THandleObject::IsAHandleObject ( (Handle) actualDataStart ) ) )
- {
- s << ", " << * ( THandleObject * ) actualDataStart;
- }
- else if ( ( fHeader.f32.fType != kRelocatable ) &&
- ( TDirectObject::IsADirectObject ( (Ptr) actualDataStart ) ) )
- {
- s << ", " << * ( TDirectObject * ) actualDataStart;
- }
- #else
- if ( ( fHeader.f32.fType == kRelocatable ) &&
- ( THandleObject::IsAHandleObject ( (Handle) identifier ) ) )
- {
- s << ", " << * ( THandleObject * ) identifier;
- }
- else if ( ( fHeader.f32.fType != kRelocatable ) &&
- ( TDirectObject::IsADirectObject ( (Ptr) start ) ) )
- {
- s << ", " << * ( TDirectObject * ) start;
- }
- #endif
- else
- {
- const LookupEntry* entry = Find ( identifier );
-
- if ( entry && entry->fInfo )
- s << ", " << (char*) entry->fInfo;
- else if ( fHeader.f32.fType == kRelocatable )
- {
- if ( !fHeader.f32.fResource)
- ShowBlockData ( s, start, size );
- }
- else if ( fHeader.f32.fType != kRelocatable )
- ShowBlockData ( s, start, size );
- }
- }
-
- #endif
-
- return s;
- }
-
- /***********************************|****************************************/
- /***********************************|****************************************/
-
- THeapWalker::THeapWalker ( const Zone* zone ):
- fZone ( zone ),
- fStart ( &((Zone*)fZone)->heapData ),
- fEnd ( fZone->bkLim ),
- fCurrent ( nil ),
- fBlock ( fZone )
- {
- }
-
- /***********************************|****************************************/
-
- THeapWalker::~THeapWalker ()
- {
- }
-
- /***********************************|****************************************/
-
- void THeapWalker::Reset ()
- {
- fCurrent = nil;
- }
-
- /***********************************|****************************************/
-
- Boolean THeapWalker::Next ()
- {
- if ( !fZone )
- {
- return false; // we were loaded in from disk, so we cannot walk the heap
- }
- if ( fCurrent == nil )
- {
- fCurrent = fStart;
- fBlock.Set ( fCurrent );
- return true;
- }
- else if ( fCurrent < fEnd )
- {
- fCurrent = fBlock.NextBlockHeader ();
- fBlock.Set ( fCurrent );
- return fCurrent < fEnd;
- }
- else
- {
- return false;
- }
- }
-
- /***********************************|****************************************/
-
- const BlockInfo& THeapWalker::GetCurrent ()
- {
- return fBlock;
- }
-
- /***********************************|****************************************/
- /***********************************|****************************************/
-
- THeapState::THeapState ():
- fCount ( 0 ),
- fBlocks ( nil )
- {
- }
-
- /***********************************|****************************************/
-
- THeapState::THeapState ( const Zone* zone ):
- fCount ( 0 ),
- fBlocks ( nil )
- {
- Copy ( zone );
- }
-
- /***********************************|****************************************/
-
- THeapState::THeapState ( const FSSpec& spec ):
- fCount ( 0 ),
- fBlocks ( nil )
- {
- Load ( spec );
- }
-
- /***********************************|****************************************/
-
- THeapState::THeapState ( const THeapState& that ):
- fCount ( 0 ),
- fBlocks ( nil )
- {
- Copy ( that );
- }
-
- /***********************************|****************************************/
-
- THeapState::~THeapState ()
- {
- delete fBlocks;
- }
-
- /***********************************|****************************************/
-
- THeapState&
- THeapState::operator = ( const THeapState& heap )
- {
- if ( this != &heap )
- Copy ( heap );
-
- return *this;
- }
-
- /***********************************|****************************************/
-
- Boolean
- THeapState::operator == ( const THeapState& heap ) const
- {
- if ( fCount != heap.fCount )
- return false;
-
- for ( unsigned long index = 0; index < fCount; index++ )
- if ( fBlocks [ index ] != heap.fBlocks [ index ] )
- return false;
-
- return true;
- }
-
- /***********************************|****************************************/
-
- Boolean
- THeapState::operator != ( const THeapState& heap ) const
- {
- if ( fCount != heap.fCount )
- return true;
-
- for ( unsigned long index = 0; index < fCount; index++ )
- if ( fBlocks [ index ] != heap.fBlocks [ index ] )
- return true;
-
- return false;
- }
-
- /***********************************|****************************************/
-
- OSErr
- THeapState::Copy ( const Zone* zone )
- {
- fCount = 0;
- THeapWalker walker ( zone );
-
- while ( walker.Next () )
- if ( walker.GetCurrent ().GetType () != BlockInfo::kFree )
- ++fCount;
-
- delete fBlocks;
-
- SetZone ( SystemZone () );
- fBlocks = new BlockInfo [ fCount ];
- SetZone ( ApplicZone () );
-
- if ( fBlocks )
- {
- unsigned long index = 0;
-
- walker.Reset ();
-
- while ( walker.Next () && index < fCount )
- {
- const BlockInfo& block = walker.GetCurrent ();
-
- if ( block.GetIdentifierAddress () != fBlocks && block.GetType () != BlockInfo::kFree )
- fBlocks [ index++ ] = block;
- }
-
- return noErr;
- }
- else
- {
- fCount = 0;
- return memFullErr;
- }
- }
-
- /***********************************|****************************************/
-
- OSErr
- THeapState::Copy ( const THeapState& heap )
- {
- delete fBlocks;
- SetZone ( SystemZone () );
- fBlocks = new BlockInfo [ heap.fCount ];
- SetZone ( ApplicZone () );
-
- if ( fBlocks )
- {
- fCount = heap.fCount;
-
- for ( unsigned long index = 0; index < fCount; index++ )
- fBlocks [ index ] = heap.fBlocks [ index ];
-
- return noErr;
- }
- else
- {
- fCount = 0;
- return memFullErr;
- }
- }
-
- /***********************************|****************************************/
-
- const BlockInfo&
- THeapState::operator [] ( unsigned long index ) const
- {
- if ( index < fCount && fBlocks )
- {
- return fBlocks [ index ];
- }
- else
- {
- static BlockInfo gBozoInfo;
- return gBozoInfo;
- }
- }
-
- /***********************************|****************************************/
-
- OSErr
- THeapState::Dump ()
- {
- return Dump ( "\pSave archive as…" );
- }
-
- /***********************************|****************************************/
-
- OSErr
- THeapState::Dump ( const StringPtr prompt )
- {
- StandardFileReply reply;
- #if defined ( BovineServer )
- reply.sfFile.vRefNum = gBovineWorkingVRefNum;
- reply.sfFile.parID = gBovineTempDirID;
- #endif
- static unsigned long gCounter;
- Str63 name;
- PLstrcpy ( name, "\pHeap Archive X" );
- name [ name [ 0 ] ] = '0' + (unsigned char) ++gCounter;
- ::StandardPutFile ( prompt, name, &reply );
- return reply.sfGood ? Dump ( reply.sfFile ) : -1;
- }
-
- /***********************************|****************************************/
-
- OSErr
- THeapState::Load ()
- {
- StandardFileReply reply;
-
- #if defined ( BovineServer )
- reply.sfFile.vRefNum = gBovineWorkingVRefNum;
- reply.sfFile.parID = gBovineTempDirID;
- #endif
-
- OSType type[4] = { kHeapArchiveType, ' ', ' ', ' '};
- ::StandardGetFile ( nil, 1, type, &reply );
- return reply.sfGood ? Load ( reply.sfFile ) : -1;
- }
-
- /***********************************|****************************************/
-
- OSErr
- THeapState::Dump ( const FSSpec& spec )
- {
- OSErr error = ::FSpCreate ( &spec, kHeapArchiveCreator, kHeapArchiveType, 0 );
-
- if ( error && error != dupFNErr )
- return error;
-
- short refNum = 0;
- error = ::FSpOpenDF ( &spec, fsWrPerm, &refNum );
-
- if ( error )
- return error;
-
- ::SetEOF ( refNum, 0 );
- ::SetFPos ( refNum, fsFromStart, 0 );
- unsigned long zero = 0;
- ::Write ( refNum, &zero, sizeof ( zero ) );
-
- for ( unsigned long index = 0; index < fCount && !error; index++ )
- error = fBlocks [ index ].Write ( refNum );
-
- ::SetFPos ( refNum, fsFromStart, 0 );
- ::Write ( refNum, &fCount, sizeof ( fCount ) );
- ::FSClose ( refNum );
-
- return error;
- }
-
- /***********************************|****************************************/
-
- OSErr
- THeapState::Load ( const FSSpec& spec )
- {
- short refNum = 0;
- OSErr error = ::FSpOpenDF ( &spec, fsRdPerm, &refNum );
-
- if ( error )
- return error;
-
- delete fBlocks;
- fBlocks = nil;
-
- ::SetFPos ( refNum, fsFromStart, 0 );
- ::Read ( refNum, &fCount, sizeof ( fCount ) );
-
- if ( fCount > 0 )
- {
- SetZone ( SystemZone () );
- fBlocks = new BlockInfo [ fCount ];
- SetZone ( ApplicZone () );
-
- if ( fBlocks )
- {
- for ( unsigned long index = 0; index < fCount && !error; index++ )
- error = fBlocks [ index ].Read ( refNum );
- }
- else
- {
- error = MemError ();
- #if debug
- chris << "failed to create array of " << fCount << " BlockInfos!" << flush;
- #endif
- fCount = 0;
- }
- }
-
- ::FSClose ( refNum );
-
- return error;
- }
-
- /***********************************|****************************************/
-
- Boolean
- THeapState::Contains ( const BlockInfo& block ) const
- {
- for ( unsigned long index = 0; index < fCount; index++ )
- if ( fBlocks [ index ] == block )
- return true;
-
- return false;
- }
-
- /***********************************|****************************************/
-
- void
- THeapState::UnmarkAllBlocks ()
- {
- MarkAllBlocks ( false );
- }
-
- /***********************************|****************************************/
-
- void
- THeapState::MarkAllBlocks ( Boolean mark )
- {
- for ( unsigned long index = 0; index < fCount; index++ )
- fBlocks [ index ].SetMarked ( mark );
- }
-
- /***********************************|****************************************/
-
- unsigned long
- THeapState::MarkedBlocksCount () const
- {
- unsigned long marked = 0;
-
- for ( unsigned long index = 0; index < fCount; index++ )
- if ( fBlocks [ index ].IsMarked () )
- marked++;
-
- return marked;
- }
-
- /***********************************|****************************************/
-
- unsigned long
- THeapState::MarkedBlocksSize () const
- {
- unsigned long size = 0;
-
- for ( unsigned long index = 0; index < fCount; index++ )
- {
- const BlockInfo& block = fBlocks [ index ];
-
- if ( block.IsMarked () )
- size += block.GetLogicalSize ();
- }
-
- return size;
- }
-
- /***********************************|****************************************/
-
- unsigned long
- THeapState::HeapSize () const
- {
- unsigned long size = 0;
-
- for ( unsigned long index = 0; index < fCount; index++ )
- size += fBlocks [ index ].GetLogicalSize ();
-
- return size;
- }
-
- /***********************************|****************************************/
-
- THeapState&
- THeapState::operator -= ( THeapState& that )
- {
- unsigned long index;
-
- for ( index = 0; index < fCount; index++ )
- {
- BlockInfo& block = fBlocks [ index ];
- block.SetMarked ( !that.Contains ( block ) );
- }
-
- unsigned long marked = MarkedBlocksCount ();
-
- if ( marked > 0 )
- {
- SetZone ( SystemZone () );
- BlockInfo* blocks = new BlockInfo [ marked ];
- SetZone ( ApplicZone () );
-
- if ( blocks )
- {
- unsigned long jndex = 0;
-
- for ( index = 0; index < fCount; index++ )
- {
- const BlockInfo& block = fBlocks [ index ];
-
- if ( block.IsMarked () )
- blocks [ jndex++ ] = block;
- }
-
- delete fBlocks;
- fBlocks = blocks;
- fCount = marked;
- }
- else
- {
- #if debug
- chris << "failed to allocate array of " << marked << " blocks!" << endl;
- #endif
- delete fBlocks;
- fBlocks = nil;
- fCount = 0;
- }
- }
- else
- {
- delete fBlocks;
- fBlocks = nil;
- fCount = 0;
- }
-
- return *this;
- }
-
- /***********************************|****************************************/
-
- THeapState&
- THeapState::operator &= ( THeapState& that )
- {
- unsigned long index;
-
- for ( index = 0; index < fCount; index++ )
- {
- BlockInfo& block = fBlocks [ index ];
- block.SetMarked ( that.Contains ( block ) );
- }
-
- unsigned long marked = MarkedBlocksCount ();
-
- if ( marked > 0 )
- {
- SetZone ( SystemZone () );
- BlockInfo* blocks = new BlockInfo [ marked ];
- SetZone ( ApplicZone () );
-
- if ( blocks )
- {
- unsigned long jndex = 0;
-
- for ( index = 0; index < fCount; index++ )
- {
- BlockInfo& block = fBlocks [ index ];
-
- if ( block.IsMarked () )
- blocks [ jndex++ ] = block;
- }
-
- delete fBlocks;
- fBlocks = blocks;
- fCount = marked;
- }
- else
- {
- #if debug
- chris << "failed to allocate array of " << marked << " blocks!" << endl;
- #endif
- delete fBlocks;
- fBlocks = nil;
- fCount = 0;
- }
- }
- else
- {
- delete fBlocks;
- fBlocks = nil;
- fCount = 0;
- }
-
- return *this;
- }
-
- /***********************************|****************************************/
-
- THeapState&
- THeapState::operator ^= ( THeapState& that )
- {
- unsigned long index;
-
- for ( index = 0; index < fCount; index++ )
- {
- BlockInfo& block = fBlocks [ index ];
- block.SetMarked ( !that.Contains ( block ) );
- }
-
- for ( index = 0; index < that.fCount; index++ )
- {
- BlockInfo& block = that.fBlocks [ index ];
- block.SetMarked ( !Contains ( block ) );
- }
-
- unsigned long marked = MarkedBlocksCount () + that.MarkedBlocksCount ();
-
- if ( marked > 0 )
- {
- SetZone ( SystemZone () );
- BlockInfo* blocks = new BlockInfo [ marked ];
- SetZone ( ApplicZone () );
-
- if ( blocks )
- {
- unsigned long jndex = 0;
-
- for ( index = 0; index < fCount; index++ )
- {
- BlockInfo& block = fBlocks [ index ];
-
- if ( block.IsMarked () )
- blocks [ jndex++ ] = block;
- }
-
- for ( index = 0; index < that.fCount; index++ )
- {
- BlockInfo& block = that.fBlocks [ index ];
-
- if ( block.IsMarked () )
- blocks [ jndex++ ] = block;
- }
-
- delete fBlocks;
- fBlocks = blocks;
- fCount = marked;
- }
- else
- {
- #if debug
- chris << "failed to allocate array of " << marked << " blocks!" << endl;
- #endif
- delete fBlocks;
- fBlocks = nil;
- fCount = 0;
- }
- }
- else
- {
- delete fBlocks;
- fBlocks = nil;
- fCount = 0;
- }
-
- return *this;
- }
-
- /***********************************|****************************************/
-
- ostream&
- THeapState::operator >> ( ostream& s ) const
- {
- s << fCount << " blocks, " << HeapSize () << " bytes" << endl;
-
- for ( unsigned long index = 0; index < fCount; index++ )
- s << index + 1 << ": " << fBlocks [ index ] << endl;
-
- return s;
- }
-
- /***********************************|****************************************/
-
- void ViewCurrentHeap ()
- {
- #if debug
- THeapState heap ( ApplicationZone () );
- chris << heap << endl;
- #endif
- }
-
- /***********************************|****************************************/
-
- void ViewArchivedHeap ()
- {
- #if debug
- THeapState heap;
- heap.Load ();
- chris << heap << endl;
- #endif
- }
-
- /***********************************|****************************************/
-
- void ArchiveCurrentHeap ()
- {
- #if debug
- THeapState heap ( ApplicationZone () );
- heap.Dump ();
- #endif
- }
-
- /***********************************|****************************************/
-
- void CompareCurrentHeapWithArchive ()
- {
- #if debug
- THeapState state1 ( ApplicationZone () ), state2;
-
- if ( state2.Load () == noErr )
- {
- state1 -= state2;
- chris << state1 << endl;
- }
- #endif
- }
-
- /***********************************|****************************************/
-